<template>
  <div class="table">
    <!-- 搜索 -->
    <div class="table__search" v-if="searchOptionsVariable.searchItems.length>0">
      <!-- 搜索项 -->
      <template v-for="(searchItem, index) in searchOptionsVariable.searchItems" :key="'search-item' + index">
        <div v-if="searchItem.show" class="table__search__item" :class="`col-span-${searchItem.grid}`">
          <!-- 搜索项名称 -->
          <div class="table__search__item__label">
            <slot :name="'search-item-label-' + searchItem.prop" :searchItem="searchItem">
              <span>{{ searchItem.label }}</span>

              <el-tooltip v-if="searchItem.tip" :content="searchItem.tip">
                <el-icon class="cursor-pointer">
                  <QuestionFilled/>
                </el-icon>
              </el-tooltip>

              <span>:</span>
            </slot>
          </div>

          <!-- 搜索项组件 -->
          <div class="table__search__item__component">
            <slot :name="'search-item-component-' + searchItem.prop" :searchItem="searchItem">
              <el-input class="w-full"
                v-if="searchItem.type === ArkTableConstant.operation.input"
                v-model.trim="searchItem.value"
                v-bind="searchItem.attributes"
                v-on="searchItem.events"
                @keyup.enter.native="clickOrEnterSearch"
              />

              <el-select class="w-full"
                v-else-if="searchItem.type === ArkTableConstant.operation.select"
                v-model="searchItem.value"
                v-bind="searchItem.attributes"
                v-on="searchItem.events"
              >
                <template v-if="searchItem.selectOptions.groups">
                  <el-option-group v-for="(groupItem,groupIndex) in searchItem.selectOptions.groups"
                    :key="'search-item-component-select'+groupIndex"
                    :label="groupItem.label"
                  >
                    <el-option v-for="(optionItem,optionIndex) in groupItem.options"
                      :key="'search-item-component-select'+groupIndex+optionIndex"
                      :label="optionItem.label"
                      :value="optionItem.value"
                    />
                  </el-option-group>
                </template>
                <template v-else-if="searchItem.selectOptions.options">
                  <el-option v-for="(optionItem,index) in searchItem.selectOptions.options"
                    :key="'search-item-component-select'+index"
                    :label="optionItem.label"
                    :value="optionItem.value"
                  />
                </template>
              </el-select>

              <el-cascader class="w-full"
                v-else-if="searchItem.type === ArkTableConstant.operation.cascader"
                v-model="searchItem.value"
                v-bind="searchItem.attributes"
                v-on="searchItem.events"
              />

              <el-date-picker class="w-full"
                v-else-if="searchItem.type === ArkTableConstant.operation.datePicker"
                v-model="searchItem.value"
                v-bind="searchItem.attributes"
                v-on="searchItem.events"
              />

              <el-time-picker class="w-full"
                v-else-if="searchItem.type === ArkTableConstant.operation.timePicker"
                v-model="searchItem.value"
                v-bind="searchItem.attributes"
                v-on="searchItem.events"
              />

              <el-time-select class="w-full"
                v-else-if="searchItem.type === ArkTableConstant.operation.timeSelect"
                v-model="searchItem.value"
                v-bind="searchItem.attributes"
                v-on="searchItem.events"
              />
            </slot>
          </div>
        </div>
      </template>

      <!-- 功能项 -->
      <div class="table__search__operation" :class="`col-span-${searchOperationGrid}`">
        <el-button type="primary" :loading="loading" @click="clickOrEnterSearch">
          <el-icon>
            <Search/>
          </el-icon>

          <span>查 询</span>
        </el-button>

        <el-button @click="clickResetSearch">重 置</el-button>

        <el-button v-if="searchOptionsVariable.searchLimit<searchOptionsVariable.searchItems.length"
          type="primary" text @click="clickCollapseOrExpand"
        >
          <span>{{ searchItemsCollapsed ? '展开' : '收起' }}</span>

          <el-icon v-if="searchItemsCollapsed">
            <ArrowDown/>
          </el-icon>
          <el-icon v-else>
            <ArrowUp/>
          </el-icon>
        </el-button>
      </div>
    </div>

    <!-- 主体 -->
    <slot>
      <div class="table__body"
        :class="{'rounded-b-lg': !(paginationOptionsVariable.show&&!paginationOptionsVariable.hasMarginTop)}"
      >
        <!-- 表格头部 -->
        <div class="table__body__header" v-if="bodyOptionsVariable.showHeader">
          <div class="table__body__header__left">{{ bodyOptionsVariable.title }}</div>
          <div class="table__body__header__right">
            <!-- 多选行操作部分 -->
            <template v-if="multiSelectionRows.length>0">
              <el-button
                v-if="bodyOptionsVariable.multiSelection.button.show === 'function'?bodyOptionsVariable.multiSelection.button.show(multiSelectionRows):bodyOptionsVariable.multiSelection.button.show"
                v-bind="bodyOptionsVariable.multiSelection.button.attributes"
                v-on="bodyOptionsVariable.multiSelection.button.events"
                @click="bodyOptionsVariable.multiSelection.button.click"
              >
                {{ bodyOptionsVariable.multiSelection.button.text }}
              </el-button>

              <slot name="body-header-right-multi-selection"></slot>
            </template>

            <!-- 表格操作部分 -->
            <el-button
              v-if="bodyOptionsVariable.button.show === 'function'?bodyOptionsVariable.button.show(multiSelectionRows):bodyOptionsVariable.button.show"
              v-bind="bodyOptionsVariable.button.attributes"
              v-on="bodyOptionsVariable.button.events"
              @click="bodyOptionsVariable.button.click"
            >
              <el-icon v-if="!bodyOptionsVariable.button.attributes.icon">
                <Plus/>
              </el-icon>

              <span>{{ bodyOptionsVariable.button.text }}</span>
            </el-button>

            <slot name="body-header-right"></slot>

            <el-tooltip content="刷新">
              <el-icon class="cursor-pointer" @click="clickRefresh()">
                <RefreshRight/>
              </el-icon>
            </el-tooltip>
          </div>
        </div>

        <!-- 表格部分 -->
        <el-table class="table__body__table" ref="table" v-loading="loading"
          v-bind="bodyOptionsVariable.table.attributes"
          v-on="bodyOptionsVariable.table.events"
        >
          <!-- 多选列 -->
          <el-table-column
            v-if="bodyOptionsVariable.multiSelection.selectionCol"
            type="selection"
            width="55"
          />

          <!-- 索引列 -->
          <el-table-column
            v-if="bodyOptionsVariable.showColIndex === 'function'?bodyOptionsVariable.showColIndex():bodyOptionsVariable.showColIndex"
            type="index"
            width="50"
          />

          <!-- 其他列 -->
          <el-table-column v-for="(columnItem, index) in bodyOptionsVariable.columns"
            :key="'body-table-column'+index"
            v-bind="columnItem"
          >
            <template v-slot="scope">
              <div class="table__body__table__column"
                :class="{
                    'justify-start': columnItem.align === ArkTableConstant.align.left,
                    'justify-center': columnItem.align === ArkTableConstant.align.center,
                    'justify-end': columnItem.align === ArkTableConstant.align.right,
              }"
              >
                <slot :name="'body-table-column-' + columnItem.prop" :row="scope.row">
                  <!-- 操作列 -->
                  <template v-if="columnItem.type===ArkTableConstant.operation.actions">
                    <!-- 未折叠 -->
                    <template v-for="(actionItem, index) in columnItem.actions"
                      :key="'body-table-column-action' + index"
                    >
                      <el-button
                        v-if="columnItem.limit>index && (typeof actionItem.show === 'function'?actionItem.show(scope.row):actionItem.show)"
                        type="primary" text
                        :disabled="typeof actionItem.disabled === 'function'?actionItem.disabled(scope.row):actionItem.disabled"
                        @click="actionItem.click(scope.row)"
                      >
                        {{ actionItem.text }}
                      </el-button>
                    </template>

                    <!-- 折叠 -->
                    <el-dropdown v-if="columnItem.limit<columnItem.actions.length">
                      <el-icon color="#007AFFFF">
                        <MoreFilled/>
                      </el-icon>

                      <template #dropdown>
                        <el-dropdown-menu>
                          <template v-for="(actionItem, index) in columnItem.actions"
                            :key="'body-table-column-action-dropdown' + index"
                          >
                            <el-dropdown-item class="!text-[#007AFFFF]"
                              v-if="columnItem.limit<=index && (typeof actionItem.show === 'function'?actionItem.show(scope.row):actionItem.show)"
                              :disabled="typeof actionItem.disabled === 'function'?actionItem.disabled(scope.row):actionItem.disabled"
                              @click="actionItem.click(scope.row)"
                            >
                              {{ actionItem.text }}
                            </el-dropdown-item>
                          </template>
                        </el-dropdown-menu>
                      </template>
                    </el-dropdown>
                  </template>
                  <el-switch v-else-if="columnItem.type===ArkTableConstant.operation.switch"
                    v-model="scope.row[columnItem.prop]"
                    active-color="#13ce66"
                    inactive-color="#ff4949"
                    v-bind="columnItem.attributes"
                    v-on="columnItem.events"
                    @change="columnItem.change($event, scope.row)"
                  />

                  <!-- 非操作列 -->
                  <template v-else>
                    <ArkTooltip :content="scope.row[columnItem.prop]"/>
                  </template>
                </slot>
              </div>
            </template>
          </el-table-column>

          <slot name="body-table-inside"></slot>
        </el-table>
      </div>
    </slot>

    <!-- 分页 -->
    <div class="table__pagination"
      v-if="paginationOptionsVariable.show === 'function'?paginationOptionsVariable.show():paginationOptionsVariable.show"
      :class="{
        'rounded-t-lg': paginationOptionsVariable.hasMarginTop,
        'mt-6': paginationOptionsVariable.hasMarginTop,
      }"
    >
      <el-pagination
        v-model:page-size="paginationOptionsVariable.pageSize"
        v-model:current-page="paginationOptionsVariable.currentPage"
        v-model:total="paginationOptionsVariable.total"
        v-bind="paginationOptionsVariable.attributes"
        v-on="paginationOptionsVariable.events"
        @change="paginationOptionsVariable.change"
      />
    </div>
  </div>
</template>

<script>
import {defineComponent} from 'vue';
import _ from 'lodash';
import ArkTableConstant from './ArkTableConstant.js';
import {ArrowDown, ArrowUp, Plus, Search} from '@element-plus/icons-vue';
import {ElMessageBox} from 'element-plus';
import ArkTooltip from '@/components/ark-component-v1/ark-tooltip/ArkTooltip.vue';

export default defineComponent({
  name: 'ArkTable',
  components: {ArkTooltip},
  props: {
    /* request返回数据数组内的键、搜索项searchOptions.searchItems.prop、主体表格列bodyOptions.columns.prop三处需要对应 */
    /**
     * 请求配置对象
     *  - request：向后端发送请求获取数据的请求函数，该函数的请求参数和返回值的结果需要注意
     *   - 请求参数结构
     *    - currentPage：当前页码（分页）
     *    - pageSize：每页数据数（分页）
     *    - 参数配置键值对：参数配置键与requestOptions.params.key相应，值与requestOptions.params.value相应
     *    - 搜索项键值对：搜索项键与searchOptions.searchItems.prop相应，值为搜索项组件v-model双向绑定值
     *   - 返回值结构
     *    - code：响应状态码
     *    - msg：响应状态描述
     *    - data：响应数据。如分页则结构如下data{}，键名可通过requestOptions.resDataKey配置；若未分页则data[]为数据部分
     *     - total：总数
     *     - rows[]：后端返回给前端的详细数据。对象键应与searchOptions.searchItems.prop和bodyOptions.columns.prop相同
     *  - error：发生错误的函数，参数为错误描述
     *  - params[]：请求参数
     *   - fromRouteQuery：是否源于路由参数query
     *   - key：参数名
     *   - value：参数值
     *  - resDataKey：返回数据结构键名配置
     *   - dataKey：数据列表键
     *   - rowsKey：详细数据键
     *   - totalKey：总数键
     */
    requestOptions: {
      type: Object,
    },
    /**
     * 搜索配置对象
     *  - columnNumber：搜索部分列数。搜索项每个占一列，功能项整个占一列
     *  - searchLimit：搜索项最大列数限制，影响功能项的展开/收起按钮
     *  - searchItems[]：搜索项列表
     *   - show：是否展示。不允许外传，根据searchLimit计算而得
     *   - grid：该搜索项占网格布局12列中的几列，传入小于等于12的整数就好，否则默认为3
     *   - prop：影响请求参数键名、插槽名称search-item-label-[prop]和search-item-component-[prop]
     *   - label：搜索项名称
     *   - tip：搜索项提示内容
     *   - type：搜索项组件类型
     *   - value：搜索项组件v-model双向绑定值
     *   - defaultValue：搜索项组件默认值，默认等于value
     *   - attributes：搜索项组件v-bind对象
     *   - selectOptions：搜索项组件选择框select的选项。不分组对象内容为{options[{label,value}]}，分组对象内容为{groups[{label,options[{label,value}]}]}
     *   - events：搜索项组件v-on对象
     */
    searchOptions: {
      type: Object,
    },
    /**
     * 主体配置对象
     *  - showHeader：是否展示头部
     *  - title：表格标题
     *  - button：头部右侧+按钮
     *   - show：是否展示。可为boolean类型，可为方法。为方法时参数multiSelectionRows，返回boolean类型
     *   - attributes：按钮v-bind对象
     *   - events：按钮v-on对象
     *   - click：按钮click事件
     *   - text：按钮文字
     *  - table：表格
     *   - attributes：表格v-bind对象
     *   - events：按钮v-on对象
     *  - columns[]：表格列v-bind对象与其他配置
     *   - align：对齐方式
     *   - prop：
     *   - label：表头文字
     *   - type：操作列或非操作类 actions/switch
     *    - type为actions时
     *     - limit：操作列最大操作数限制
     *     - actions[]：操作列表
     *      - show：按钮是否展示。可为boolean类型，可为方法。为方法时参数scope.row，返回boolean类型
     *      - disabled：操作按钮是否禁用。可为boolean类型，可为方法。为方法时参数scope.row，返回boolean类型
     *      - click：操作按钮点击事件，参数scope.row
     *      - text：按钮文字
     *    - type为switch时
     *     - attributes：开关v-bind对象
     *     - events：开关v-on对象
     *     - change：开关change事件，参数$event和scope.row
     *  - showColIndex：是否展示索引。可为boolean类型，可为方法
     *  - multiSelection：多选
     *   - selectionCol：是否展示选择列
     *   - button：头部右侧多选删除按钮
     *    - show：是否展示。可为boolean类型，可为方法。为方法时参数multiSelectionRows，返回boolean类型
     *    - attributes：按钮v-bind对象
     *    - events：按钮v-on对象
     *    - click：按钮click事件
     *    - confirm：确认弹出框
     *     - text：提示文字
     *     - confirm：确认事件，参数选中行对象数组
     *     - cancel：取消事件，参数选中行对象数组
     *    - text：按钮文字
     */
    bodyOptions: {
      type: Object,
    },
    /**
     * 分页配置对象
     *  - show：是否展示。可为boolean类型，可为方法
     *  - hasMarginTop：是否存在上外边距
     *  - pageSize：每页显示条目个数
     *  - currentPage：当前页数
     *  - total：总条目数
     *  - attributes：分页v-bind对象
     *  - events：分页v-on对象
     *  - change：分页currentPage或pageSize改变事件
     */
    paginationOptions: {
      type: Object,
    },
  },
  data() {
    const thisVue = this;
    return {
      ArkTableConstant: ArkTableConstant,
      requestOptionsVariable: {
        request: () => { },
        error: (msg) => {
          console.error(msg);
        },
        params: [],
        resDataKey: {
          dataKey: 'data',
          rowsKey: 'rows',
          totalKey: 'total',
        }
      },
      searchOptionsVariable: {
        columnNumber: 4,
        searchLimit: 3,
        searchItems: [],
      },
      bodyOptionsVariable: {
        showHeader: true,
        title: '查询表格',
        button: {
          show: true,
          attributes: {
            type: 'primary',
          },
          events: {},
          text: '新增'
        },
        table: {
          attributes: {},
          events: {
            'selection-change': (selection) => {
              thisVue.multiSelectionRows = selection;
            },
          },
        },
        columns: [],
        showColIndex: true,
        multiSelection: {
          selectionCol: false,
          button: {
            show: true,
            attributes: {
              type: 'danger',
              plain: true,
              loading: false
            },
            events: {},
            click: () => {
              thisVue.clickMultiDefaultOperator();
            },
            confirm: {
              text: '此操作将删除所选择的内容, 是否继续?',
              confirm: (selectedRows) => { },
              cancel: (selectedRows) => { },
            },
            text: '删除',
          }
        },
      },
      paginationOptionsVariable: {
        show: true,
        hasMarginTop: false,
        pageSize: 10,
        currentPage: 1,
        total: 0,
        attributes: {
          small: true,
          background: true,
          layout: 'total, sizes, prev, pager, next, jumper',
        },
        events: {},
        change: (currentPage, pageSize) => {
          if (thisVue.disablePaginationChange) {
            return;
          }

          thisVue.paginationOptionsVariable.currentPage = currentPage;
          thisVue.paginationOptionsVariable.pageSize = pageSize;

          thisVue.$nextTick(() => {
            thisVue.getTableData();
          });
        },
      },
      loading: false,
      searchItemsCollapsed: true,
      multiSelectionRows: [],
      disablePaginationChange: false,
    };
  },
  computed: {
    searchOperationGrid() {
      let columnNumber = this.searchOptionsVariable.columnNumber;
      let searchLimit = this.searchOptionsVariable.searchLimit;
      let searchItemCount = this.searchOptionsVariable.searchItems.length;

      // 折叠状态
      if (this.searchItemsCollapsed && searchItemCount > searchLimit) {
        searchItemCount = searchLimit;
      }

      // 计算功能项所占列数
      let grid = 12;
      if (searchItemCount < columnNumber) {
        grid = ((columnNumber - searchItemCount) * 12) / columnNumber;
      } else if (searchItemCount > columnNumber) {
        grid = ((columnNumber - (searchItemCount % columnNumber)) * 12) / columnNumber;
      }

      return grid;
    },
    requestParams() {
      let result = {};

      // 传入的参数数据
      const params = this.requestOptionsVariable.params;
      if (params && params.length > 0) {
        params.forEach(item => {
          if (item.fromRouteQuery) {
            result[item.key] = this.$route.query[item.key];
            return;
          }

          result[item.key] = item.value;
        });
      }

      // 分页数据
      const paginationOptionsVariable = this.paginationOptionsVariable;
      if (paginationOptionsVariable.show) {
        result.pageSize = paginationOptionsVariable.pageSize;
        result.currentPage = paginationOptionsVariable.currentPage;
      }

      // 搜索项数据
      const searchItems = this.searchOptionsVariable.searchItems;
      if (searchItems && searchItems.length > 0) {
        searchItems.forEach(item => {
          // 值判空
          if (item.value === null || item.value === undefined) {
            return;
          }

          // 字符串长度判空
          if (typeof item.value === 'string' && item.value.trim().length === 0) {
            return;
          }

          result[item.prop] = item.value;
        });
      }

      return result;
    },
  },
  created() {
    this.initAllOptionsVariable();
    this.getTableData();
  },
  methods: {
    initAllOptionsVariable() {
      // 根据传入requestOptions初始化requestOptionsVariable
      const requestOptions = _.cloneDeep(this.requestOptions);
      const requestOptionsVariable = _.cloneDeep(this.requestOptionsVariable);
      this.requestOptionsVariable = _.defaultsDeep(requestOptions, requestOptionsVariable);

      // 根据传入searchOptions初始化searchOptionsVariable
      const searchOptions = _.cloneDeep(this.searchOptions);
      const searchOptionsVariable = _.cloneDeep(this.searchOptionsVariable);
      this.searchOptionsVariable = this.setSearchOptionsVariable(searchOptions, searchOptionsVariable);

      // 根据传入bodyOptions初始化bodyOptionsVariable
      const bodyOptions = _.cloneDeep(this.bodyOptions);
      const bodyOptionsVariable = _.cloneDeep(this.bodyOptionsVariable);
      this.bodyOptionsVariable = this.setBodyOptionsVariable(bodyOptions, bodyOptionsVariable);

      // 根据传入paginationOptions初始化paginationOptionsVariable
      const paginationOptions = _.cloneDeep(this.paginationOptions);
      const paginationOptionsVariable = _.cloneDeep(this.paginationOptionsVariable);
      this.paginationOptionsVariable = _.defaultsDeep(paginationOptions, paginationOptionsVariable);
    },
    setSearchOptionsVariable(options, optionsVariable) {
      optionsVariable = _.defaultsDeep(options, optionsVariable);
      optionsVariable.searchItems.forEach((item, index) => {
        delete item.show;

        if (item.grid && (Number.isNaN(Number(item.grid)) || item.grid > 12)) {
          delete item.grid;
          console.warn('请检查您searchOptionsVariable.searchItems中的grid配置，该配置需为数字且<=12');
        }

        const searchItemsOptionsVariable = {
          show: optionsVariable.searchLimit > index,
          grid: (12 / optionsVariable.columnNumber),
          prop: index.toString(),
          label: '搜索项名称',
          tip: item.tip,
          type: ArkTableConstant.operation.input,
          value: '',
          defaultValue: item.value,
          attributes: item.type === ArkTableConstant.operation.select ?
            {placeholder: '请选择', clearable: true} : {placeholder: '请输入', clearable: true},
          selectOptions: item.type === ArkTableConstant.operation.select ? {options: []} : null,
          events: {},
        };

        _.defaultsDeep(item, searchItemsOptionsVariable);
      });

      return optionsVariable;
    },
    setBodyOptionsVariable(options, optionsVariable) {
      optionsVariable = _.defaultsDeep(options, optionsVariable);
      optionsVariable.columns.forEach((item, index) => {
        let differentTypeOptions = {};
        if (item.type === ArkTableConstant.operation.actions) {
          differentTypeOptions = {
            type: ArkTableConstant.operation.actions,
            limit: 4,
            actions: item.actions.map(item => {
              return {
                show: true,
                disabled: false,
                click: (row) => {
                },
                text: '操作'
              };
            })
          };
        } else if (item.type === ArkTableConstant.operation.switch) {
          differentTypeOptions = {
            type: ArkTableConstant.operation.switch,
            events: {},
            change: (event, row) => {
            }
          };
        }

        const columnsOptionsVariable = {
          align: ArkTableConstant.align.left,
          label: '表头名称',
          prop: index.toString(),
          ...differentTypeOptions,
        };

        _.defaultsDeep(item, columnsOptionsVariable);
      });

      return optionsVariable;
    },
    getTableData() {
      this.loading = true;

      Promise.resolve(this.requestOptionsVariable.request(this.requestParams)).then(data => {
        // 数据为空
        if (!data) {
          this.requestOptionsVariable.error('请求函数获取的数据为空');
        }

        // 未设置dataKey
        if (!this.requestOptionsVariable.resDataKey.dataKey) {
          this.bodyOptionsVariable.table.attributes.data = data;
          return;
        }

        // 未分页 or 未设置rowsKey
        const dataKey = data[this.requestOptionsVariable.resDataKey.dataKey];
        if (!dataKey) {
          this.requestOptionsVariable.error('请求函数获取的数据Key配置错误，请检查requestOptionsVariable.resDataKey.dataKey');
          return;
        }
        if (!this.paginationOptionsVariable.show || !this.requestOptionsVariable.resDataKey.rowsKey) {
          this.bodyOptionsVariable.table.attributes.data = dataKey;
          return;
        }

        // 分页
        const rowsKey = dataKey[this.requestOptionsVariable.resDataKey.rowsKey];
        if (!rowsKey) {
          this.requestOptionsVariable.error('请求函数获取的分页数据Key配置错误，请检查requestOptionsVariable.resDataKey.rowsKey');
          return;
        }
        const totalKey = dataKey[this.requestOptionsVariable.resDataKey.totalKey];
        if (!totalKey) {
          this.requestOptionsVariable.error('请求函数获取的分页数据总数Key配置错误，请检查requestOptionsVariable.resDataKey.totalKey');
          return;
        }

        this.bodyOptionsVariable.table.attributes.data = rowsKey;
        this.paginationOptionsVariable.total = totalKey;
      }).finally(() => {
        this.loading = false;
      });
    },
    clickOrEnterSearch() {
      if (this.paginationOptionsVariable.currentPage !== 1) {
        this.disablePaginationChange = true;
      }
      this.paginationOptionsVariable.currentPage = 1;

      this.$nextTick(() => {
        this.getTableData();
        this.disablePaginationChange = false;
      });
    },
    clickResetSearch() {
      this.searchOptionsVariable.searchItems.forEach(item => {
        item.value = item.defaultValue;
      });

      if (this.paginationOptionsVariable.currentPage !== 1) {
        this.disablePaginationChange = true;
      }
      this.paginationOptionsVariable.currentPage = 1;

      this.$nextTick(() => {
        this.getTableData();
        this.disablePaginationChange = false;
      });
    },
    clickCollapseOrExpand() {
      this.searchItemsCollapsed = !this.searchItemsCollapsed;

      const searchOptionsVariable = this.searchOptionsVariable;
      if (this.searchItemsCollapsed) { // 折叠
        searchOptionsVariable.searchItems.forEach((item, index) => {
          item.show = searchOptionsVariable.searchLimit > index;
        });
      } else { // 展开
        searchOptionsVariable.searchItems.forEach((item, index) => {
          item.show = true;
        });
      }
    },
    clickRefresh() {
      if (this.paginationOptionsVariable.currentPage !== 1) {
        this.disablePaginationChange = true;
      }
      this.paginationOptionsVariable.currentPage = 1;

      this.$nextTick(() => {
        this.getTableData();
        this.disablePaginationChange = false;
      });
    },
    clickMultiDefaultOperator() {
      const button = this.bodyOptionsVariable.multiSelection.button;
      const multiSelectionRows = this.multiSelectionRows;

      ElMessageBox.confirm(button.confirm.text, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).then(() => {
        button.attributes.loading = true;
        Promise.resolve(button.confirm.confirm(multiSelectionRows)).finally(() => {
          button.attributes.loading = false;
        });
      }).catch(() => {
        button.confirm.cancel(multiSelectionRows);
      });
    },

    // 供外部调用，内部未使用
    getElTableInstance() {
      return this.$refs.table;
    },
    setColumns(columns) {
      this.bodyOptionsVariable.columns = columns;
    },
    setRequest(request) {
      this.requestOptionsVariable.request = request;
    },
  },
});
</script>

<style scoped>
.table {
  @apply text-base relative;

  .table__search {
    @apply bg-white p-6 mb-6 rounded-lg;
    @apply grid grid-cols-12 gap-6;

    .table__search__item {
      @apply flex items-center gap-x-2;

      .table__search__item__label {
        @apply shrink-0 flex items-center gap-x-0.5;
      }

      .table__search__item__component {
        @apply flex-1;

        & > :deep(div) {
          @apply w-full;
        }
      }
    }

    .table__search__operation {
      @apply text-end flex gap-x-2.5 justify-end items-center;

      & > button {
        @apply m-0
      }

      & > button.is-text {
        @apply px-0;

        &:hover, &:active, &:focus {
          @apply bg-transparent;
        }
      }
    }
  }

  .table__body {
    @apply bg-white px-6 pt-6 rounded-t-lg;

    .table__body__header {
      @apply mb-4 flex justify-between items-center;

      .table__body__header__left {
        @apply font-semibold text-lg text-[#17233d];
      }

      .table__body__header__right {
        @apply flex items-center gap-x-3;

        & > button {
          @apply m-0;
        }
      }
    }

    .table__body__table {
      & :deep(.el-table__cell) {
        @apply py-2;
      }

      & :deep(.el-table__header-wrapper .el-table__cell) {
        @apply bg-[#FAFAFA];
      }

      & :deep(.cell) {
        @apply flex items-center;
      }

      .table__body__table__column {
        @apply inline-flex items-center flex-wrap gap-1.5;

        & > button.is-text {
          @apply m-0 px-0;

          &:hover, &:active, &:focus {
            @apply bg-transparent;
          }
        }
      }
    }
  }

  .table__pagination {
    @apply bg-white py-6 rounded-b-lg flex justify-center;
  }
}
</style>
